import java.awt.*;
import java.util.*;

import javax.swing.ImageIcon;


public class Robot {

	//Images for red/blue robots
	public static final ImageIcon redRobot = new ImageIcon("RedRobot.png");
	public static final ImageIcon blueRobot = new ImageIcon("BlueRobot.png");
	public static final ImageIcon userRobot = new ImageIcon("UserRobot.png");

	public final static int Y_DIMENSION = 50;
	public final static int X_DIMENSION = 100;
	private int identifier;
	private Point position; //This is the center point

	//All constants are integers from 0 to 100
	private int delayConstant;
	private int speedConstant;
	private int pickupConstant;
	private int shootConstant;
	public static Random randomizer = new Random();
	private ArrayList<Zone> zoneList;
	private int validX, validY;

	private ArrayList<GamePiece> heldGamePieceList = new ArrayList<GamePiece>(); 	
	private Alliance alliance = Alliance.neutral;
	private State state = State.neutral;
	private RobotThread thread;

	//Enumerated type. Use either Alliance.red or Alliance.blue
	public static enum Alliance{red, blue, neutral}
	public static enum State{score, collect, block, neutral}

	public Robot() {
		//blank robot for robot selection purposes
	}

	public Robot (Alliance alliance, int identifier, Point position, int delayConstant, int speedConstant, int pickupConstant, int shootConstant, State state) {
		this.alliance = alliance;
		this.identifier = identifier;
		this.position = position;
		this.delayConstant = delayConstant;
		this.speedConstant = speedConstant/5;
		this.pickupConstant = pickupConstant;
		this.shootConstant = shootConstant;
		this.state = state;
	}


	//sets the robots position to the specified value
	public void move(int a, int b) {
		this.setPosition(new Point(a, b));

	}

	//change the position of the robot
	public void move(Point point) {
		this.setPosition(point);
	}

	//shoots a ball
	public boolean shoot(){

		//Tells the the gamepiece it is no longer carried
		heldGamePieceList.get(0).setCarried(false);
		heldGamePieceList.get(0).setTargeted(false);

		int shot = randomizer.nextInt(100);

		//Checks to see if shot is successful if it fails bounce is called
		if(shot >= shootConstant){
			heldGamePieceList.get(0).bounce();
			heldGamePieceList.remove(0);

			return false;
		}

		else{

			//adds one to red score if it is a red robot
			if (alliance == Robot.Alliance.red) {
				ControlPanel.updateRedScore(1);
				ControlPanel.output("Red Scores!");
			}
			//adds one to blue score if it is a blue robot.
			if (alliance == Robot.Alliance.blue) {
				ControlPanel.updateBlueScore(1);
				ControlPanel.output("Blue Scores!");
			}
			//puts GamePiece in a 
			heldGamePieceList.get(0).setPosition(new Point(50 + randomizer.nextInt(650), 50 + randomizer.nextInt(300)));
			heldGamePieceList.remove(0);
			return true;
		}

	}

	public boolean pickup(GamePiece piece){

		if(state == State.collect && !piece.isCarried()){ 
			//Makes sure that the piece isn't carried by another robot

			int pick = randomizer.nextInt(100);

			//checks to see if the pickup is successful
			if(pick >= pickupConstant){
				return false;
			}
			else{
				//if successful adds the GamePiece to the list
				heldGamePieceList.add(piece);
				piece.setOwner(this); 
				//Sets the owner of the game piece to the robot that this method is invoked upon
				piece.setCarried(true);
				ControlPanel.output("Successful pickup!");
				return true;
			}
		}

		else{
			return false;
		}
	}

	public void drawRobot(Graphics page){ 
		//This method draws the robot onto the given page based on the center point

		if(alliance == Alliance.blue && identifier == 1){
			userRobot.paintIcon(null,page,
					position.x-X_DIMENSION/2,
					position.y-Y_DIMENSION/2);
		}

		else if(alliance == Alliance.red){

			redRobot.paintIcon(null,page,
					position.x-X_DIMENSION/2,
					position.y-Y_DIMENSION/2);
			page.drawString(Integer.toString(identifier), position.x, position.y+10);
		}

		else if(alliance == Alliance.blue){

			blueRobot.paintIcon(null,page,
					position.x-X_DIMENSION/2,
					position.y-Y_DIMENSION/2);
			page.drawString(Integer.toString(identifier), position.x, position.y+10);
		}
		//draws the state of the robot and the current target
		page.drawString(state.toString(), position.x, position.y);
		try{
			page.drawString(thread.collectionTarget.getPosition().toString(), position.x, position.y+40);
		}
		catch(NullPointerException e){}

	}

	//true if the move is valid, false if not 
	public synchronized boolean moveIsValid(RobotThread.Direction direction){
		boolean moveIsValid = true;

		//Direction is converted into a point
		switch (direction) {
		case up:
			validX = position.x;
			validY = position.y - speedConstant;

			break;
		case down:
			validX = position.x;
			validY = position.y + speedConstant;

			break;

		case left:
			validX = position.x - speedConstant;
			validY = position.y;


			break;
		case right:
			validX = position.x + speedConstant;
			validY = position.y;
			break;
		}
		Point nextPoint = new Point(validX, validY);

		//checks the validity based on robots
		if(checkRobots(nextPoint)){
			moveIsValid = false;
		}
		//checks the validity based on zones
		if(!checkZones(nextPoint)){
			moveIsValid = false;
		}
		return moveIsValid;
	}

	//overridden method based on points rather than direction
	public synchronized boolean moveIsValid(Point point){
		boolean moveIsValid = true;

		//checks the validity based on robots
		if(checkRobots(point)){
			moveIsValid = false;
		}

		//checks the validity based on zones
		if(!checkZones(point)){
			moveIsValid = false;
		}
		return moveIsValid;
	}

	//true if robot is in the way	
	public boolean checkRobots(Point p){

		int rightXRobot, leftXRobot, topYRobot, bottomYRobot;
		int rightXZone, leftXZone, topYZone, bottomYZone;
		boolean robotInTheWay;

		robotInTheWay = false;

		//gernerates an arraylist of all robots except for this robot
		ArrayList<Robot> robotArray = new ArrayList<Robot>();
		for(Robot aRobot : RoboticsProjectPanel.getRobotArrayList()){
			robotArray.add(aRobot);
		}
		robotArray.remove(this);

		leftXRobot = p.x - X_DIMENSION/2;
		rightXRobot = p.x + X_DIMENSION/2;
		topYRobot = p.y - Y_DIMENSION/2;
		bottomYRobot = p.y + Y_DIMENSION/2;

		//for each robot except itself: check to see if contact made
		for(Robot testRobot : robotArray){
			leftXZone = testRobot.getXPosition() - X_DIMENSION/2;
			rightXZone = testRobot.getXPosition() + X_DIMENSION/2;
			topYZone = testRobot.getYPosition() - Y_DIMENSION/2;
			bottomYZone = testRobot.getYPosition() + Y_DIMENSION/2;			

			if((rightXRobot >  leftXZone - 50) && (rightXRobot <  rightXZone + 50)){
				if((topYRobot <=  bottomYZone) && (topYRobot >=  topYZone))
					robotInTheWay = true;
				else if((bottomYRobot <= bottomYZone) && (bottomYRobot >=  topYZone)){
					robotInTheWay = true;
				}

			}
			else if((leftXRobot <  rightXZone + 50) && (leftXRobot >  leftXZone -50)){
				if((topYRobot <=  bottomYZone) && (topYRobot >=  topYZone))
					robotInTheWay = true;
				else if((bottomYRobot <=  bottomYZone) && (bottomYRobot >=  topYZone)){
					robotInTheWay = true;
				}
			}
			else if((bottomYRobot >  topYZone + 50) && (bottomYRobot <  bottomYZone - 50)){
				if((rightXRobot <= rightXZone) && (rightXRobot >=  leftXZone))
					robotInTheWay = true;
				else if((leftXRobot >=  leftXZone) && (leftXRobot <=  rightXZone)){
					robotInTheWay = true;
				}
			}
			else if((topYRobot >  topYZone + 50) && (topYRobot <  bottomYZone - 50)){
				if((rightXRobot <  rightXZone) && (rightXRobot >=  leftXZone))
					robotInTheWay = true;
				else if((leftXRobot >=  leftXZone) && (leftXRobot <=  rightXZone)){
					robotInTheWay = true;
				}
			}
		}
		return robotInTheWay;
	}

	//returns false if move is invalid
	public boolean checkZones(Point p){

		zoneList = RoboticsProjectPanel.field.getZoneList();

		//for all the zones
		for(int i=0; i<zoneList.size() -6; i++){

			//store a temporary zone

			if(zoneList.get(i).getAlliance() != alliance){
				Zone tempZone = zoneList.get(i);

				//for all x coordinates from the min to max
				for(int j= p.x - Robot.X_DIMENSION/2; j<p.x + Robot.X_DIMENSION/2; j++){

					//and for all y coordinates from the min to max
					for(int k= p.y - Robot.Y_DIMENSION/2; k<p.y + Robot.Y_DIMENSION/2; k++){

						//If this point is within the zone's x range AND
						//the y range, the move is no longer valid
						int xmin = tempZone.getXMin();
						int xmax = tempZone.getXMax();
						int ymin = tempZone.getYMin();
						int ymax = tempZone.getYMax();

						if((xmin <= j) && (j <= xmax) && (ymin <= k) && (k <= ymax)){
							return false;
						}

					}
				}
			}
			else{}
		}

		return true;
	}

	//Getters and setters
	public int getDelay(){
		return delayConstant;
	}

	public int getSpeed(){
		return speedConstant;
	}

	public int getPickup(){
		return pickupConstant;
	}

	public int getShoot(){

		return shootConstant;
	}

	public void setDelay(int delayConstant){
		this.delayConstant = delayConstant;
	}

	public void setSpeed(int speedConstant){
		this.speedConstant = speedConstant;
	}

	public void setPickup(int pickupConstant){
		this.pickupConstant = pickupConstant;
	}

	public void setShoot(int shootConstant){
		this.shootConstant = shootConstant;
	}

	public int getXPosition(){
		return position.x;
	}

	public int getYPosition(){
		return position.y;
	}
	public State getState(){
		return state;
	}
	public void setState(State newState){
		state = newState;
	}
	public boolean findState() {

		//Figures out the state of the robot
		if(state == State.neutral){
			state = State.collect;
		}
		if (state == state.collect && heldGamePieceList.size()>0){
			state = state.score;
			return false;	
		}
		else if(state == state.score && heldGamePieceList.size()<1){
			state = state.collect;
			return false;

		}
		else{
			state = state.collect;

		}
		return false;
	}
	
	public Point getPosition(){
		return position;
	}
	
	public Robot.Alliance getAlliance(){
		return alliance;
	}

	public int getIdentifier() {
		return identifier;
	}

	public void setIdentifier(int identifier) {
		this.identifier = identifier;
	}

	public void setPosition(Point position) {
		this.position = position;
	}

	public void setAlliance(Alliance alliance) {
		this.alliance = alliance;
	}
	
	public void start(){
		thread.start();
	}
	
	public void createThread(){
		thread = new RobotThread(this);
	}
	
	public ArrayList<GamePiece> getHeldGamePieceList() {
		return heldGamePieceList;
	}

	public void wakeThread(){
		thread.goAgain();
	}
}

/* 

ORIGINAL ATTEMPT A.K.A. BACK UP PLAN

//Overloaded method. This one takes in a direction instead of a point.
public synchronized boolean moveIsValid(RobotThread.Direction direction) {

	int robotCase = 0;
	if(alliance == Alliance.blue){
		robotCase = identifier-1;
	}
	else if(alliance == Alliance.red){
		robotCase = (identifier-1)+3;
	}
	//list of zones acquired from the field
	zoneList = RoboticsProjectPanel.field.getZoneList();

	//Direction is converted into a point
	switch (direction) {
	case up:
		validX = position.x;
		validY = position.y - speedConstant;

		break;
	case down:
		validX = position.x;
		validY = position.y + speedConstant;

		break;

	case left:
		validX = position.x - speedConstant;
		validY = position.y;


		break;
	case right:
		validX = position.x + speedConstant;
		validY = position.y;
		break;
	}
	int tempX = validX;
	int tempY = validY;

	//for all the zones
	for(int i=0; i<zoneList.size()-6; i++){

		//store a temporary zone

		if(zoneList.get(i).getAlliance() != alliance){
			Zone tempZone = zoneList.get(i);

			//for all x coordinates from the min to max
			for(int j= tempX - Robot.X_DIMENSION/2; j<tempX + Robot.X_DIMENSION/2; j++){

				//and for all y coordinates from the min to max
				for(int k= tempY - Robot.Y_DIMENSION/2; k<tempY + Robot.Y_DIMENSION/2; k++){

					//If this point is within the zone's x range AND
					//the y range, the move is no longer valid
					int xmin = tempZone.getXMin();
					int xmax = tempZone.getXMax();
					int ymin = tempZone.getYMin();
					int ymax = tempZone.getYMax();

					if((xmin <= j) && (j <= xmax) && (ymin <= k) && (k <= ymax)){
						//									System.out.println("J is: " + j);
						//									System.out.println("K is:" + k);
						return false;
					}

				}
			}
		}
		else{}
	}
	for(int i=zoneList.size()-6; i<zoneList.size(); i++){
		if(i!=zoneList.size()-(6-robotCase)){
			//store a temporary zone

			//if(zoneList.get(i).getAlliance() != alliance){
			Zone tempZone = zoneList.get(i);



			//for all x coordinates from the min to max
			for(int j= tempX - Robot.X_DIMENSION/2; j<tempX + Robot.X_DIMENSION/2; j++){

				//and for all y coordinates from the min to max
				for(int k= tempY - Robot.Y_DIMENSION/2; k<tempY + Robot.Y_DIMENSION/2; k++){

					//If this point is within the zone's x range AND
					//the y range, the move is no longer valid
					int xmin = tempZone.getXMin();
					int xmax = tempZone.getXMax();
					int ymin = tempZone.getYMin();
					int ymax = tempZone.getYMax();

					if((xmin <= j) && (j <= xmax) && (ymin <= k) && (k <= ymax)){
						//									System.out.println("J is: " + j);
						//									System.out.println("K is:" + k);
						return false;
					}
				}
			}
		}
	}
	return true;


}
*/